package com.etxxy.web.security.session;

import java.io.Serializable;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;

import org.apache.shiro.session.Session;
import org.apache.shiro.session.UnknownSessionException;
import org.apache.shiro.session.mgt.eis.AbstractSessionDAO;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.etxxy.common.util.SerializableUtil;
import com.etxxy.web.security.RedisManager;

/**
 * @category redisSession自定义，可实现前缀方便管理
 * @author yiz
 *
 */
public class RedisSessionDAO extends AbstractSessionDAO {
	 private static Logger logger = LoggerFactory.getLogger(RedisSessionDAO.class);  
	    private RedisManager redisManager;  
	      
	    /** 
	     * The Redis key prefix for the sessions  
	     */  
	    private String keyPrefix = "shiro_redis_session:";  
	      
	    @Override  
	    public void update(Session session) throws UnknownSessionException {  
	        this.saveSession(session);  
	    }  
	      
	    /** 
	     * save session 
	     * @param session 
	     * @throws UnknownSessionException 
	     */  
	    private void saveSession(Session session) throws UnknownSessionException{  
	        if(session == null || session.getId() == null){  
	            logger.error("session or session id is null");  
	            return;  
	        }
	        session.setTimeout(redisManager.getDefaultExpire()*1000);        
	        this.redisManager.setex(getByteKey(session.getId()), SerializableUtil.serialize(session), redisManager.getDefaultExpire());  
	    }  
	  
	    @Override  
	    public void delete(Session session) {  
	        if(session == null || session.getId() == null){  
	            logger.error("session or session id is null");  
	            return;  
	        }  
	        if(session == null || session.getId() == null){  
	            logger.error("session or session id is null");  
	            return;  
	        }  
	        redisManager.remove(getByteKey(session.getId()));  
	  
	    }  
	  
	    //用来统计当前活动的session  
	    @Override  
	    public Collection<Session> getActiveSessions() {  
	        Set<Session> sessions = new HashSet<Session>();  
	          
	        Set<byte[]> keys = redisManager.byteKeys(this.keyPrefix + "*");  
	        if(keys != null && keys.size()>0){  
	            for(byte[] key:keys){  
	                Session s = (Session)redisManager.getObject(key);
	                sessions.add(s);  
	            }  
	        }  
	          
	        return sessions;  
	    }  
	  
	    @Override  
	    protected Serializable doCreate(Session session) {  
	        Serializable sessionId = this.generateSessionId(session);    
	        this.assignSessionId(session, sessionId);  
	        this.saveSession(session);  
	        return sessionId;  
	    }  
	  
	    @Override  
	    protected Session doReadSession(Serializable sessionId) {  
	        if(sessionId == null){  
	            logger.error("session id is null");  
	            return null;  
	        }  
	        //sessionID读取
	        Session s = (Session)redisManager.getObject(getByteKey(sessionId));  
	        return s;  
	    }  
	    
	    /** 
	     * 获得byte[]型的key 
	     * @param key 
	     * @return 
	     */  
	    private byte[] getByteKey(Serializable sessionId){  
	        String preKey = this.keyPrefix + sessionId;  
	        return preKey.getBytes();  
	    }  
	    
	    private String getKey(Serializable sessionId){
	    	String preKey = this.keyPrefix + sessionId;  
	    	return preKey;
	    }
	  
	    public RedisManager getRedisManager() {  
	        return redisManager;  
	    }  
	  
	    public void setRedisManager(RedisManager redisManager) {  
	        this.redisManager = redisManager;  
	    }  
	  
	    /** 
	     * Returns the Redis session keys 
	     * prefix. 
	     * @return The prefix 
	     */  
	    public String getKeyPrefix() {  
	        return keyPrefix;  
	    }  
	  
	    /** 
	     * Sets the Redis sessions key  
	     * prefix. 
	     * @param keyPrefix The prefix 
	     */  
	    public void setKeyPrefix(String keyPrefix) {  
	        this.keyPrefix = keyPrefix;  
	    }  
	    
	    

}
